﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TireService.Data;
using DevExpress.Web.ASPxCallback;
using System.Web.Security;

namespace TireService.Business.Portal.UserControls
{
    public partial class ucReplaceCar : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void callbackReplaceCarPanel_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
        {
            LoadUserControl(Convert.ToInt32(e.Parameter));
        }

        /// <summary>
        /// Public function for loading usercontrol
        /// </summary>
        public void LoadUserControl(int CarId)
        {
            // Show usercontrol edit form
            pReplaceCar.Visible = true;

            // Initiate datalayer
            TireServiceDB db = new TireServiceDB();

            if (CarId != 0)
            {
                LoadCar(CarId, db);
            }
            else
            {
                // Error
                throw new ArgumentException("Bil blev ikke fundet");
            }
        }

        /// <summary>
        /// Function that load car
        /// </summary>
        /// <param name="CarId">Id on car to be replaced with new car</param>
        /// <param name="db">Connection to database</param>
        private void LoadCar(int CarId, TireServiceDB db)
        {
            // Fetch Car
            Car car = db.GetCar(CarId);

            // Set values in replacecar form
            if (car != null)
            {
                Customer customer = db.GetCustomer(car.CustomerId);

                lblCustomerIdValue.Text = customer.CustomerId.ToString();
                lblCustomerNameValue.Text = customer.Name;
                lblCarRegistrationNumberValue.Text = car.RegistrationNumber;

                // Bind data to dropdown list
                ddlNewCarBrand.DataSource = db.GetCarBrand();
                ddlNewCarBrand.TextField = "Description";
                ddlNewCarBrand.ValueField = "CarBrandId";
                ddlNewCarBrand.DataBind();

                ddlNewCarStatus.DataSource = db.GetCarStatus();
                ddlNewCarStatus.TextField = "Description";
                ddlNewCarStatus.ValueField = "CarStatusId";
                ddlNewCarStatus.DataBind();

                // Show possible adresses to select from if tireset should be returned
                ddlReplaceCarReturnCustomerTireSetSelectAddress.Items.Clear();
                string add1 = customer.Address + "|" + customer.ZipCode + "|" + customer.City;
                string add2 = customer.SecondaryAddress + "|" + customer.SecondaryZipCode + "|" + customer.SecondaryCity;
                string add3 = "-- Anden adresse --";
                ddlReplaceCarReturnCustomerTireSetSelectAddress.Items.Add(add1, 0);
                ddlReplaceCarReturnCustomerTireSetSelectAddress.Items.Add(add2, 1);
                ddlReplaceCarReturnCustomerTireSetSelectAddress.Items.Add(add3, 2);

                // Show possible adresses to select from if tireset should be picked up - new car
                ddlReplaceCarNewCarReturnCustomerTireSetSelectAddress.Items.Clear();
                ddlReplaceCarNewCarReturnCustomerTireSetSelectAddress.Items.Add(add1, 0);
                ddlReplaceCarNewCarReturnCustomerTireSetSelectAddress.Items.Add(add2, 1);
                ddlReplaceCarNewCarReturnCustomerTireSetSelectAddress.Items.Add(add3, 2);
            }
            else
            {
                // Error
                throw new ArgumentException("Bil blev ikke fundet");
            }
        }

        /// <summary>
        /// Callback function that replace car with new car that is created
        /// </summary>
        protected void callBackReplaceCar_Callback(object sender, CallbackEventArgs e)
        {
            try
            {
                // Get values from client 
                // 0: CarId - int
                // 1: TireSetAction - int
                // 2: RegistrationNumber - string
                // 3: BrandId - int
                // 4: Model - string
                // 5: EngineSize - string
                // 6: FuelType - int
                // 7: Year - int
                // 8: Color - string 
                // 9: CurrentTireSet - int  
                // 10: EmailConfirmation (true/false) 
                // 11: InvoiceCustomer (true/false) (optional)
                // 12: InvoicePrice (optional) - decimal
                // 13: Address (optional) - string
                // 14: ZipCode (optional) - string
                // 15: City (optional) - string
                // 16: Remark to address (optional) - string
                // 17: Note to employee (optional) - string
                // 18: Action for other tireset on new car - int
                // 19: InvoiceCustomer for new car tireset pickup (true/false)
                // 20: Invoiceprice for pickup of new tireset - decimal
                // 21: Pickup Address (optional) - string
                // 22: Pickup ZipCode (optional) - string
                // 23: Pickup City (optional) - string
                // 24: Pickup Remark to address (optional) - string
                // 25: Pickup Note to employee (optional) - string
                // 26. New car status

                string[] param = e.Parameter.Split('|');

                // Get UserId (for logging)
                Guid UserId = new Guid(Membership.GetUser().ProviderUserKey.ToString());

                // Initiate datalayer
                TireServiceDB db = new TireServiceDB();

                // Get car
                Car car = db.GetCar(Convert.ToInt32(param[0]));

                // Get Customer Subscription
                CustomerSubscription customersubscription = db.GetCustomerSubscription(Convert.ToInt32(car.CustomerSubscriptionId));

                // TODO: Validate if old open tasks on car and tiresets - moving is then not possible

                // Create new car
                Car newcar = new Car();
                newcar.CustomerSubscriptionId = car.CustomerSubscriptionId;
                newcar.CustomerId = car.CustomerId;
                newcar.RegistrationNumber = Convert.ToString(param[2]);
                newcar.CarBrandId = Convert.ToInt32(param[3]);
                newcar.Model = Convert.ToString(param[4]);
                newcar.EngineSize = Convert.ToString(param[5]);
                newcar.FuelType = Convert.ToInt32(param[6]);
                newcar.Year = Convert.ToInt32(param[7]);
                newcar.Color = Convert.ToString(param[8]);
                newcar.CarStatusId = Convert.ToInt32(param[26]); // TODO: Consider if status is require service drive, create task automatic???

                db.AddCar(newcar);

                // Deactivate current car
                car.CarStatusId = (int)Shared.CarStatus.InActive;
                car.CustomerSubscriptionId = null;

                // Initiate customersubscription log
                CustomerSubscriptionLogBLL customersubscriptionlogBLL = new CustomerSubscriptionLogBLL();

                int TireSetAction = Convert.ToInt32(param[1]); // 0: Existing tireset can be used on new car, 1: Deliver tires to customer selected address, 2: Return from warehouse, 3: Tireset already returned, 4: Keep tireset
                int NewTireSetAction = Convert.ToInt32(param[18]); // 0: We will get tires on first service, 1: Pickup tires, 2: We have the tires

                // Instantiate task business logic layer
                TaskBLL taskBLL = new TaskBLL();

                // Declare invoice variable if invoicing is needed
                string invoiceid = string.Empty;

                // Declare string as input for message on tireset action
                string tiresetaction = "";

                // Get paying customer for invoicing and emailing confirmation
                CustomerBLL customerBLL = new CustomerBLL();
                int PayingCustomerId = customerBLL.GetPayingCustomerId(db, car.CustomerId);
                Customer payingcustomer = db.GetCustomer(PayingCustomerId);

                // Initiate E-conomic interface
                EconomicInterface ecoInterface = new EconomicInterface();

                // Instantiate tiresetlog business logic
                TireSetLogBLL tiresetlogBLL = new TireSetLogBLL();

                // Placeholder for adding new tires to new car
                TireSet tireset1 = new TireSet();
                TireSet tireset2 = new TireSet();

                if (TireSetAction == 0)
                {
                    // Existing tireset can be used on new car - move to new car

                    // Get tiresets for current car (tireset that are not returned or inactive)
                    int[] tiresetstatus = new int[] { (int)Shared.TireSetStatus.OnStock, (int)Shared.TireSetStatus.AwaitsMoveToStock, (int)Shared.TireSetStatus.MountedOnCar, (int)Shared.TireSetStatus.PlacedAtCustomer, (int)Shared.TireSetStatus.StockedAtCustomer };
                    List<TireSet> tiresets = db.GetCarTireSetByTireSetStatus(car.CarId, tiresetstatus);

                    if (tiresets.Count == 0)
                    {
                        throw new ArgumentException("Ingen hjulsæt blev fundet på nuværende bil - overførsel til ny bil kan derfor ikke gennemføres.");
                    }

                    foreach (TireSet tireset in tiresets)
                    {
                        car.TireSets.Remove(tireset);
                        newcar.TireSets.Add(tireset);

                        // Create log for tiresets
                        tiresetlogBLL.CreateTireSetLog(db, tireset, DateTime.Now, tireset.TireSetStatusId, tireset.TireSetStatusId, UserId, "Udskiftning af bil med ny (Fra: " + car.RegistrationNumber + " Til: " + newcar.RegistrationNumber, null, null, null, null, null);
                    }

                    tiresetaction += "Hjul fra gammel bil skal bruges på den nye bil";

                    // Create subscription log
                    customersubscriptionlogBLL.CreateCustomerSubscriptionLog(db, customersubscription, (int)Shared.SubscriptionLogAction.Edited, UserId, "Bil udskiftet med ny (Fra: " + car.RegistrationNumber + " Til: " + newcar.RegistrationNumber + ") - hjulsæt genbruges på ny bil");
                }

                if (TireSetAction == 1)
                {
                    // Deliver the tireset back to the customer

                    // Get tiresets on stock
                    int[] tiresetstatus = new int[] { (int)Shared.TireSetStatus.OnStock };
                    List<TireSet> tiresets = db.GetCarTireSetByTireSetStatus(car.CarId, tiresetstatus);

                    if (tiresets.Count == 0 | tiresets.Count > 1)
                    {
                        throw new ArgumentException("Hjulsæt ikke opbevaret på lager for kunden - udlevering kan derfor ikke gennemføres.");
                    }

                    // Create servicedrive task
                    Task task = taskBLL.CreateTask(db,
                                                    null,
                                                    (int)Shared.TaskType.ServiceDrive,
                                                    (int)Shared.TaskDetailType.ServiceDrive_ReturnTire,
                                                    (int)Shared.TaskTypeStatus.ServiceDrive_Created,
                                                    car.CustomerId,
                                                    car.CarId,
                                                    tiresets.First().TireSetId,
                                                    Convert.ToString(param[13]),
                                                    Convert.ToString(param[14]),
                                                    Convert.ToString(param[15]),
                                                    0,
                                                    Convert.ToString(param[16]),
                                                    Convert.ToString(param[13]),
                                                    Convert.ToString(param[14]),
                                                    Convert.ToString(param[15]),
                                                    0,
                                                    Convert.ToString(param[16]),
                                                    Convert.ToString(param[17]),
                                                    1,
                                                    UserId,
                                                    true);

                    tiresetaction += "Hjulsæt til gammel bil bliver leveret på adressen: " + Convert.ToString(param[13]) + ", " + Convert.ToString(param[14]) + " " + Convert.ToString(param[15]) + " indenfor 12 arbejdsdage";

                    // Create subscription log
                    customersubscriptionlogBLL.CreateCustomerSubscriptionLog(db, customersubscription, (int)Shared.SubscriptionLogAction.Edited, UserId, "Bil udskiftet med ny (Fra: " + car.RegistrationNumber + " Til: " + newcar.RegistrationNumber + ") - levering af hjul hos kunden");
                }

                if (TireSetAction == 2)
                {
                    // Customer will pick-up tires on stock

                    // Get tiresets on stock
                    int[] tiresetstatus = new int[] { (int)Shared.TireSetStatus.OnStock };
                    List<TireSet> tiresets = db.GetCarTireSetByTireSetStatus(car.CarId, tiresetstatus);

                    if (tiresets.Count == 0 | tiresets.Count > 1)
                    {
                        throw new ArgumentException("Hjulsæt ikke opbevaret på lager for kunden - udlevering til kunden på lager kan derfor ikke gennemføres.");
                    }

                    // Create stock task - handout of tires to customer from stock
                    Task task = taskBLL.CreateTask(db,
                                                    null,
                                                    (int)Shared.TaskType.StockTask,
                                                    (int)Shared.TaskDetailType.StockTask_HandoutTireSet,
                                                    (int)Shared.TaskTypeStatus.StockTask_Created,
                                                    customersubscription.CustomerId,
                                                    car.CarId,
                                                    tiresets.First().TireSetId,
                                                    null,
                                                    null,
                                                    null,
                                                    0,
                                                    null,
                                                    null,
                                                    null,
                                                    null,
                                                    0,
                                                    null,
                                                    "Udlevering af hjul til kunde - bil erstattet med ny",
                                                    4,
                                                    UserId,
                                                    true);

                    tiresetaction += "Hjulsæt kan afhentes på vores lager for gammel bil.";

                    // Create subscription log
                    customersubscriptionlogBLL.CreateCustomerSubscriptionLog(db, customersubscription, (int)Shared.SubscriptionLogAction.Edited, UserId, "Bil udskiftet med ny (Fra: " + car.RegistrationNumber + " Til: " + newcar.RegistrationNumber + ") - kunde afhenter hjul på lager");
                }

                if (TireSetAction == 3)
                {
                    // Tireset already returned / at the customers location
                    int[] tiresetstatus = new int[] { (int)Shared.TireSetStatus.OnStock, (int)Shared.TireSetStatus.AwaitsMoveToStock, (int)Shared.TireSetStatus.PlacedAtCustomer, (int)Shared.TireSetStatus.StockedAtCustomer };
                    List<TireSet> tiresets = db.GetCarTireSetByTireSetStatus(car.CarId, tiresetstatus);

                    if (tiresets.Count == 0 | tiresets.Count > 1)
                    {
                        throw new ArgumentException("Hjulsæt ikke fundet - udskiftning af bil kan ikke gennemføres - kontakt systemadministration.");
                    }

                    TireSet tireset = tiresets.First();

                    // Create log for tiresets
                    tiresetlogBLL.CreateTireSetLog(db, tireset, DateTime.Now, tireset.TireSetStatusId, (int)Shared.TireSetStatus.ReturnedToCustomer, UserId, "Udskiftning af bil med ny", null, null, null, null, null);

                    // Change status on the tireset
                    tireset.TireSetStatusId = (int)Shared.TireSetStatus.ReturnedToCustomer;

                    tiresetaction += "Hjulsæt er leveret retur for gammel bil.";

                    // Create subscription log
                    customersubscriptionlogBLL.CreateCustomerSubscriptionLog(db, customersubscription, (int)Shared.SubscriptionLogAction.Edited, UserId, "Bil udskiftet med ny (Fra: " + car.RegistrationNumber + " Til: " + newcar.RegistrationNumber + ") - kunde har fået hjulene retur");
                }

                if (TireSetAction == 4)
                {
                    // Customer do not want tires back

                    // Get tiresets on stock
                    int[] tiresetstatus = new int[] { (int)Shared.TireSetStatus.OnStock };
                    List<TireSet> tiresets = db.GetCarTireSetByTireSetStatus(car.CarId, tiresetstatus);

                    if (tiresets.Count == 0 | tiresets.Count > 1)
                    {
                        throw new ArgumentException("Hjulsæt ikke opbevaret på lager for kunden - kassering af hjul kan derfor ikke gennemføres - kontakt system administration.");
                    }

                    // Create stock task - discard of tireset due to customer do not want it
                    Task task = taskBLL.CreateTask(db,
                                                    null,
                                                    (int)Shared.TaskType.StockTask,
                                                    (int)Shared.TaskDetailType.StockTask_DiscardTireSet,
                                                    (int)Shared.TaskTypeStatus.StockTask_Created,
                                                    customersubscription.CustomerId,
                                                    car.CarId,
                                                    tiresets.First().TireSetId,
                                                    null,
                                                    null,
                                                    null,
                                                    0,
                                                    null,
                                                    null,
                                                    null,
                                                    null,
                                                    0,
                                                    null,
                                                    "Hjulsæt kunde ikke ønsker efter erstatning af bil med ny",
                                                    4,
                                                    UserId,
                                                    true);

                    tiresetaction += "De har angivet de ikke ønsker de opbevarede hjulsæt længere for den gamle bil.";

                    // Create subscription log
                    customersubscriptionlogBLL.CreateCustomerSubscriptionLog(db, customersubscription, (int)Shared.SubscriptionLogAction.Edited, UserId, "Bil udskiftet med ny (Fra: " + car.RegistrationNumber + " Til: " + newcar.RegistrationNumber + ") - kunde ønsker ikke længere hjulene");
                }

                if (TireSetAction != 0)
                {
                    // Add tiresets for new car
                    TireSetBLL tiresetBLL = new TireSetBLL();
                    ContainerCargoRoomBLL containerBLL = new ContainerCargoRoomBLL();

                    // Determine what tires are on the car
                    int tireset1status, tireset2status;
                    int? tireset1container, tireset2container;

                    int tiresetonstockstatus = (int)Shared.TireSetStatus.OnStock;

                    if (Convert.ToString(param[18]) == "0")
                    {
                        // Customer has tireset
                        tiresetonstockstatus = (int)Shared.TireSetStatus.PlacedAtCustomer;
                    }
                    if (Convert.ToString(param[18]) == "1")
                    {
                        // Tirest should be picked up - create task
                        tiresetonstockstatus = (int)Shared.TireSetStatus.PlacedAtCustomer;
                    }
                    if (Convert.ToString(param[18]) == "2")
                    {
                        // We already have the tireset
                        tiresetonstockstatus = (int)Shared.TireSetStatus.OnStock;

                        // TODO: Make code for selecting right container
                    }

                    // TODO: Not the best solution - should maybe be another smarter method
                    Customer customer = db.GetCustomer(car.CustomerId);

                    if (Convert.ToString(param[9]) == "0")
                    {
                        // Winter tires on car
                        tireset1status = tiresetonstockstatus;
                        tireset1container = containerBLL.ReturnNearestContainerCargoRoomId(db, float.Parse(customer.LatitudePrimary.ToString()), float.Parse(customer.LongitudePrimary.ToString()));
                        tireset2status = (int)Shared.TireSetStatus.MountedOnCar;
                        tireset2container = null;
                    }
                    else
                    {
                        // Summer tires on car
                        tireset1status = (int)Shared.TireSetStatus.MountedOnCar;
                        tireset1container = null;
                        tireset2status = tiresetonstockstatus;
                        tireset2container = containerBLL.ReturnNearestContainerCargoRoomId(db, float.Parse(customer.LatitudePrimary.ToString()), float.Parse(customer.LongitudePrimary.ToString()));
                    }

                    tiresetBLL.UpdateTireSet(
                                        db,
                                        tireset1,
                                        car,
                                        (int)Shared.TireType.SummerTires,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        false,
                                        false,
                                        false,
                                        false,
                                        false,
                                        null,
                                        null,
                                        tireset1status,
                                        null,
                                        tireset1container,
                                        true,
                                        false,
                                        null,
                                        UserId,
                                        null,
                                        true
                                    );

                    tiresetBLL.UpdateTireSet(
                                        db,
                                        tireset2,
                                        car,
                                        (int)Shared.TireType.WinterTires,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        false,
                                        false,
                                        false,
                                        false,
                                        false,
                                        null,
                                        null,
                                        tireset2status,
                                        null,
                                        tireset2container,
                                        true,
                                        false,
                                        null,
                                        UserId,
                                        null,
                                        true
                                    );
                }

                // Check if invoicing needed
                if (Convert.ToBoolean(param[4]) | Convert.ToBoolean(param[19]))
                {
                    // Create invoice

                    // Create orderline for invoicing
                    List<EconomicInterface.EcoOrderLine> orderlines = new List<EconomicInterface.EcoOrderLine>();

                    if (Convert.ToBoolean(param[4]))
                    {
                        // Delivery of tireset

                        EconomicInterface.EcoOrderLine orderline = new EconomicInterface.EcoOrderLine();
                        orderline.ProductNumber = 8; // TODO: Make more dynamic
                        orderline.Description = "Aflevering af hjul for bil: " + car.RegistrationNumber;
                        orderline.Quantity = 1;
                        orderline.UnitPrice = Convert.ToDecimal(param[12]);

                        orderlines.Add(orderline);
                    }

                    if (Convert.ToBoolean(param[19]))
                    {
                        // Pickup of tireset

                        EconomicInterface.EcoOrderLine orderline = new EconomicInterface.EcoOrderLine();
                        orderline.ProductNumber = 3; // TODO: Make more dynamic
                        orderline.Description = "Afhentning af hjul for bil: " + newcar.RegistrationNumber;
                        orderline.Quantity = 1;
                        orderline.UnitPrice = Convert.ToDecimal(param[20]);

                        orderlines.Add(orderline);
                    }

                    // Create invoice in e-conomic
                    invoiceid = ecoInterface.CreateInvoice(db, customersubscription.CustomerId, car, orderlines, (!payingcustomer.ManualInvoicing));

                    // Extend text info for customer email with invoice
                    tiresetaction += "<br><br>I email er vedlagt faktura for udkørsler ifht. hjulsæt.";
                }

                // Commit changes to database
                db.SubmitChanges();

                // Check if new car tireset should be picked up
                if (Convert.ToString(param[18]) == "1")
                {
                    int tiresetid;

                    // Check which tires that should be picked up
                    if (Convert.ToString(param[9]) == "0")
                    {
                        tiresetid = tireset1.TireSetId;
                    }
                    else
                    {
                        tiresetid = tireset2.TireSetId;
                    }

                    // Create servicedrive task
                    Task task = taskBLL.CreateTask(db,
                                                    null,
                                                    (int)Shared.TaskType.ServiceDrive,
                                                    (int)Shared.TaskDetailType.ServiceDrive_PickUpTire,
                                                    (int)Shared.TaskTypeStatus.ServiceDrive_Created,
                                                    car.CustomerId,
                                                    newcar.CarId,
                                                    tiresetid,
                                                    Convert.ToString(param[13]),
                                                    Convert.ToString(param[14]),
                                                    Convert.ToString(param[15]),
                                                    0,
                                                    Convert.ToString(param[16]),
                                                    Convert.ToString(param[13]),
                                                    Convert.ToString(param[14]),
                                                    Convert.ToString(param[15]),
                                                    0,
                                                    Convert.ToString(param[16]),
                                                    Convert.ToString(param[17]),
                                                    1,
                                                    UserId,
                                                    true);

                    tiresetaction += "Hjulsæt til bil bliver afhentet på adressen: " + Convert.ToString(param[13]) + ", " + Convert.ToString(param[14]) + " " + Convert.ToString(param[15]);

                    // Create subscription log
                    customersubscriptionlogBLL.CreateCustomerSubscriptionLog(db, customersubscription, (int)Shared.SubscriptionLogAction.Edited, UserId, "Bil udskiftet med ny (Fra: " + car.RegistrationNumber + " Til: " + newcar.RegistrationNumber + ") - hjul til ny bil afhentes");

                    // Submit new changes with task created
                    db.SubmitChanges();
                }

                // Check if email confirmation should be send to customer
                if (Convert.ToBoolean(param[10]))
                {
                    // Send email to customer (paying customer is always the one who receives email notification

                    // Initiate email service
                    EmailNotificationServices emailService = new EmailNotificationServices();

                    CustomerSubscriptionBLL customersubscriptionBLL = new CustomerSubscriptionBLL();

                    // Check if invoicing has happend
                    if (Convert.ToBoolean(param[4]) | Convert.ToBoolean(param[19]))
                    {
                        emailService.ReplaceCar_SendCustomerNotification(payingcustomer.CustomerId, payingcustomer.Email, payingcustomer.Name, customersubscriptionBLL.GetSubscriptionNumber(customersubscription), car.RegistrationNumber, newcar.RegistrationNumber, tiresetaction, invoiceid, ecoInterface.GetInvoice(Convert.ToInt32(invoiceid)), "Faktura" + invoiceid + ".pdf");
                    }
                    else
                    {
                        emailService.ReplaceCar_SendCustomerNotification(payingcustomer.CustomerId, payingcustomer.Email, payingcustomer.Name, customersubscriptionBLL.GetSubscriptionNumber(customersubscription), car.RegistrationNumber, newcar.RegistrationNumber, tiresetaction);
                    }

                }

                // Dispose database connection
                db.Dispose();
            }
            catch (Exception ex)
            {
                // Error
                throw new ArgumentException("Fejl opstod: " + ex.Message);
            }
        }
    }
}